#include <tls.h>

using namespace std;
using namespace boost::asio;

int main(int, char**){
    default_random_engine re;

    ip::tcp::iostream tcp_stream("127.0.0.1", "4321"); //打开连接服务器的TCP Stream
    cout << "Client open socket" << endl;

    Hello client_hello_instance;
    unsigned char client_hello_rand[32];
    for (int i = 31;i >= 0; --i){
        client_hello_instance.random[i] = re();
        client_hello_rand[i] = client_hello_instance.random[i];
    } // 产生随机数
    client_hello_instance.cipher_suites.push_back(0x01);
    client_hello_instance.cipher_suites.push_back(0x13);
    std::vector<unsigned char> wrapped_hello = wrap_hello(client_hello_instance); // 产生client_hello的TCP包
    for (int i = wrapped_hello.size() - 1;i >= 0; --i){
        tcp_stream << (char)wrapped_hello[i]; // 向流中写入client_hello包
    }
    cout << "Client send client hello" << endl;

    Hello server_hello_instance;
    parse_clienthello(server_hello_instance, tcp_stream); // 解析server_hello包
    cout << "Client get server hello" << endl;
    unsigned char server_hello_rand[32];
    for (int i = 31;i >= 0; --i){
        server_hello_rand[i] = server_hello_instance.random[i]; // 保存server_hello随机数
    }

    Certificate ser_cert_instance;
    parse_certificate(ser_cert_instance, tcp_stream); // 解析server_的x509包
    CertificateEntry ser_cert_x509_instance = ser_cert_instance.certificate_list[0];
    fstream data_out;
    data_out.open("/tmp/ser_crt.pem", ios::out);
    for (int i = ser_cert_x509_instance.cert_data.size() - 1;i >= 0 ; --i){
        data_out << (char)ser_cert_x509_instance.cert_data[i];
    } // 储存证书
    data_out.close();
    auto ser_botan_x509_instance = Botan::X509_Certificate("/tmp/ser_crt.pem"); // 解析证书
    cout << "Client get certificate" << endl;
    string x509_string = ser_botan_x509_instance.to_string();
    data_out.open("/tmp/ser_pubkey.pem", ios::out);
    data_out << x509_string; // 写入公钥
    data_out.close();
    std::unique_ptr<Botan::Public_Key> ser_x509_pubkey{ Botan::X509::load_key("/tmp/ser_pubkey.pem") }; // 读取公钥
    cout << x509_string;

    CertificateEntry cli_x509;
    fstream data_in;
    data_in.open("./Client/ca.crt", ios::in); // 读取Client证书
    string data;
    string buf;
    while (getline(data_in, buf))
    {
        buf += "\n";
        data.append(buf);
    }
    cli_x509.cert_data.assign(data.begin(), data.end());
    cli_x509.certificate_type = CertificateType::X509;
    Certificate cli_cert_instance;
    cli_cert_instance.certificate_list.push_back(cli_x509);
    std::vector<unsigned char> wrapped_cert = wrap_certificate(cli_cert_instance);  // 发送Client证书包
    for (int i = wrapped_cert.size() - 1;i >= 0; --i){
        tcp_stream << (char)wrapped_cert[i];
    }
    data_in.close();
    cout << "Client send certificate" << endl;

    vector<uint8_t> key_raw;
    key_raw.resize(32);
    for (int i = 31;i >= 0; --i){
        key_raw[i] = re();
    } // 产生随机数
    Botan::AutoSeeded_RNG rng;
    Botan::PK_Encryptor_EME enc(*ser_x509_pubkey, rng, "EME-PKCS1-v1_5");
    KeyShareEntry key_instance;
    key_instance.key_exchange = enc.encrypt(key_raw, rng); // 用服务器公钥加密随机数
    // for (int i = 0;i < key_instance.key_exchange.size(); ++i){
    //     cout << (unsigned short)key_instance.key_exchange[i] << " ";
    // }
    std::vector<unsigned char> wrapped_key_instance = wrap_keyshare(key_instance, true);
    for (int i = wrapped_key_instance.size() - 1;i >= 0; --i){
        tcp_stream << (char)wrapped_key_instance[i];
    } // 发送key_exchange包
    cout << "Client send keyshare" << endl;

    data_in.open("./Client/payload.txt", ios::in);
    data.clear();
    while (getline(data_in, buf))
    {
        buf += "\n";
        data.append(buf);
    }// 读取待发送文本
    cout << data;
    vector<uint8_t> key;
    vector<uint8_t> iv;
    key.resize(16);
    iv.resize(16);
    for (int i = 0;i < 16; ++i){
        key[i] = key_raw[i];
        iv[i]  = key_raw[i + 16];
    }
//    vector<uint8_t> block = Botan::hex_decode("00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF");
    vector<uint8_t> block(data.begin(), data.end());
    const auto aes_enc = Botan::Cipher_Mode::create_or_throw("AES-128/CBC/PKCS7", Botan::Cipher_Dir::Encryption);
    aes_enc->set_key(key);
    // Botan::secure_vector<uint8_t> iv = rng.random_vec(aes_enc->default_nonce_length());
    aes_enc->start(iv);
    aes_enc->finish(block);// 用AES加密文本
    Payload payload_instance;
    payload_instance.payload = block;
    std::vector<unsigned char> wrapped_payload = wrap_payload(payload_instance, true);
    for (int i = wrapped_payload.size() - 1; i >= 0; --i){
        tcp_stream << (char)wrapped_payload[i];
    }// 发送加密后的文本
    cout << "Client send payload" << endl;
   return 0;
}
